<?php

namespace Gnway\Ticket\Rest\Util;

use Gnway\Ticket\Rest\Container\RestContainer;
use InvalidArgumentException, ReflectionException, Closure;

final class FunctionUtils
{

  /**
   * Don't let anyone instantiate this class
   */
  private function __construct() {}

  /**
   * Invoke a function.
   *
   * @param string|Closure $callable
   * @param array          $parameters
   * @return mixed
   * @throws ReflectionException
   */
  public static function invoke($callable, array $parameters = [])
  {
    if (!self::invokable($callable)) {
      throw new InvalidArgumentException(sprintf('Argument 1 passed to %s() must be function, %s given.',
        __METHOD__, gettype($callable)));
    }

    return $callable(...self::getParameters($callable, $parameters));
  }

  /**
   * Invokable
   *
   * @param Closure|string $callable
   * @return bool
   */
  public static function invokable($callable): bool
  {
    if (!($callable instanceof Closure) && !function_exists($callable)) {
      return FALSE;
    }

    return is_callable($callable);
  }

  /**
   * Resolve the parameters of a specified function.
   *
   * @param string|Closure $func
   * @param array          $parameters
   * @return array
   * @throws ReflectionException
   */
  public static function getParameters($func, array $parameters = []): array
  {
    return RestContainer::getFunctionParameters($func, $parameters);
  }
}